﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.IO.Ports;
using Microsoft.Kinect;


namespace enhanced_command_interface
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    ///
    //TODO: Modify MovementController class to manage SerialPort object on its own.
    //      Extend KinectInterface class to allow caller to select between each sensor.
    //      Play around with RepeatButtons and see if it's best to switch to one-click-and-leave-running style or not. 
    //      Implement keyboard (easy) / controller (not so easy) functionality.

    public partial class MainWindow : Window
    {

        SerialPort serialPort = new SerialPort();
        MovementController movementController = new MovementController();
        KinectInterface kinectInterface = new KinectInterface();
        bool enableKeyboardMovement = false;

        public MainWindow()
        {
            InitializeComponent();
            refreshPorts();
            toggleMotionButtonsVisibility(false);
            portStopButton.IsEnabled = false;
            stopKinectButton.IsEnabled = false;
        }
        

        private void portRefreshButton_Click(object sender, RoutedEventArgs e)
        {
            refreshPorts();
        }

        private void portSelectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                //We probably want all of this to be handled by the MovementController object. This implies giving the MovementController the SerialDataReceivedEventHandler function so it can be the one to subscribe events.
                serialPort = movementController.getSerial();
                serialPort.PortName = portSelectionComboBox.Text;
                serialPort.BaudRate = 9600;
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                serialPort.Open();
                toggleMotionButtonsVisibility(true);
                portSelectButton.IsEnabled = false;
                portStopButton.IsEnabled = true;
                enableKeyboardMovement = true;

            }

            catch (Exception ex)
            {
                  MessageBox.Show(ex.Message, "ERROR");
            }
        }

        private void portStopButton_Click(object sender, RoutedEventArgs e)
        {
            //Send a stop movement command to the robot if it's in the process of moving when we close the serial connection.
            if (movementController.getMovementDirection() != MovementController.Directions.Stop)
            {
                movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.stop);
                movementController.StopMovement();
            }

            serialPort.Close();
            toggleMotionButtonsVisibility(false);
            portSelectButton.IsEnabled = true;
            portStopButton.IsEnabled = false;
            enableKeyboardMovement = false;
        }

        private void refreshPorts()
        {
            portSelectionComboBox.Items.Clear();
            string[] comPorts = SerialPort.GetPortNames();

            foreach (string port in comPorts)
            {
                portSelectionComboBox.Items.Add(port);
            }

            //Automatically display the comm port if there's only one. Ask the user to select a port otherwise.
            if (comPorts.Length == 1)
            {
                portSelectionComboBox.SelectedIndex = 0;
            }
            else
            {
                portSelectionComboBox.Text = "--Select Port--";
            }
        }

        private void receivedDataClearButton_Click(object sender, RoutedEventArgs e)
        {
            receivedDataTextBox.Clear();
        }

        private void startKinectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                kinectInterface.Refresh();
                kinectInterface.StartKinect();
                this.kinectSensorImage.Source = kinectInterface.getBitMap();
                stopKinectButton.IsEnabled = true;
                startKinectButton.IsEnabled = false;
            }

            catch (NullReferenceException)
            {
                MessageBox.Show("No Kinect Detected (Is it plugged in?)", "ERROR");
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("No Kinect Detected (Is it plugged in?)", "ERROR");
                this.kinectSensorImage.Source = null;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "ERROR");
            }
        }

        private void stopKinectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                kinectInterface.StopKinect();
                startKinectButton.IsEnabled = true;
                stopKinectButton.IsEnabled = false;
                this.kinectSensorImage.Source = null;
            }

            catch (NullReferenceException)
            {
                MessageBox.Show("No Kinect Detected (Is it plugged in?)", "ERROR");
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("No Kinect Detected (Is it plugged in?)", "ERROR");
                this.kinectSensorImage.Source = null;
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message, "ERROR");
            }
        }

        private void toggleMotionButtonsVisibility(bool toggle)
        {
            northWestMovementButton.IsEnabled = toggle;
            northMovementButton.IsEnabled = toggle;
            northEastMovementButton.IsEnabled = toggle;
            southWestMovementButton.IsEnabled = toggle;
            southMovementButton.IsEnabled = toggle;
            southEastMovementButton.IsEnabled = toggle;
            westMovementButton.IsEnabled = toggle;
            eastMovementButton.IsEnabled = toggle;
            stopMovementButton.IsEnabled = toggle;
        }

        private void KeyboardMovementControl(object sender, KeyEventArgs e)
        {
            if (enableKeyboardMovement == true)
            {
                if (Keyboard.IsKeyDown(Key.W) && Keyboard.IsKeyDown(Key.A) && (movementController.getMovementDirection() != MovementController.Directions.NorthWest))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.northWest);
                    movementController.MoveNorthWest();
                }

                if (Keyboard.IsKeyDown(Key.W) && Keyboard.IsKeyUp(Key.A) && Keyboard.IsKeyUp(Key.D) && (movementController.getMovementDirection() != MovementController.Directions.North))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.north);
                    movementController.MoveNorth();
                }

                if (Keyboard.IsKeyDown(Key.W) && Keyboard.IsKeyDown(Key.D) && (movementController.getMovementDirection() != MovementController.Directions.NorthEast))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.northEast);
                    movementController.MoveNorthEast();
                }

                if (Keyboard.IsKeyDown(Key.A) && Keyboard.IsKeyUp(Key.W) && Keyboard.IsKeyUp(Key.S) && (movementController.getMovementDirection() != MovementController.Directions.West))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.west);
                    movementController.MoveWest();
                }

                if (Keyboard.IsKeyDown(Key.D) && Keyboard.IsKeyUp(Key.W) && Keyboard.IsKeyUp(Key.S) && (movementController.getMovementDirection() != MovementController.Directions.East))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.east);
                    movementController.MoveEast();
                }

                if (Keyboard.IsKeyDown(Key.S) && Keyboard.IsKeyDown(Key.A) && (movementController.getMovementDirection() != MovementController.Directions.SouthWest))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.southWest);
                    movementController.MoveSouthWest();
                }

                if (Keyboard.IsKeyDown(Key.S) && Keyboard.IsKeyUp(Key.A) && Keyboard.IsKeyUp(Key.D) && (movementController.getMovementDirection() != MovementController.Directions.South))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.south);
                    movementController.MoveSouth();
                }

                if (Keyboard.IsKeyDown(Key.S) && Keyboard.IsKeyDown(Key.D) && (movementController.getMovementDirection() != MovementController.Directions.SouthEast))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.southEast);
                    movementController.MoveSouthEast();
                }

                if (Keyboard.IsKeyDown(Key.F) && (movementController.getMovementDirection() != MovementController.Directions.Stop))
                {
                    movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.stop);
                    movementController.StopMovement();
                }

            }

        }


        private void northMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.north);
            movementController.MoveNorth();
        }

        private void northEastMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.northEast);
            movementController.MoveNorthEast();
        }

        private void northWestMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.northWest);
            movementController.MoveNorthWest();
        }

        private void westMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.west);
            movementController.MoveWest();
        }

        private void eastMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.east);
            movementController.MoveEast();
        }

        private void southWestMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.southWest);
            movementController.MoveSouthWest();
        }

        private void southMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.south);
            movementController.MoveSouth();
        }

        private void southEastMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.southEast);
            movementController.MoveSouthEast();
        }

        private void stopMovementButton_Click(object sender, RoutedEventArgs e)
        {
            movementDirectionImage.Source = Misc.jpegToImageSource(RessourceImages.stop);
            movementController.StopMovement();
        }

        StringBuilder receivedOverSerial = new StringBuilder();
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string receivedOverSerial = sp.ReadExisting();

            receivedDataTextBox.Dispatcher.Invoke(new Action(() => receivedDataTextBox.AppendText(receivedOverSerial)));
        }


    }
}
